#include "background_task.h"
#include "func.h"
#include <thread>
#include <iostream>
#include <string>
#include "thread_guard.h"
void start_thread_with_fake_func();
void start_thread_with_closure();
void do_something_in_current_thread(int num);
void test_throw_with_join_v0();
void test_throw_with_join_v1();
void test_detach();
void runThrowWithJoin();

void hello() {
    std::cout << "hello concurrent world\n"; 
}

int main(int argc, char const *argv[]) 
{
    std::thread thread(hello);
    thread.join();
    return 0;
}

void runThrowWithJoin() {

    try
    {
       test_throw_with_join_v1();
    }
    catch(const char *excp)
    {
        std::cout << std::string(excp) << std::endl;
    }
}
void test_throw_with_join_v1() {
    int aIndex = 10;
    func heavy_work(aIndex);
    std::thread my_thread(heavy_work);
    thread_gurad guard(my_thread);
    try
    {
        do_something_in_current_thread(8);
    }
    catch(const int num)
    {
        std::cout << "exception num : " <<num << std::endl;
        throw "An error happened ...";
    }
}

void test_throw_with_join_v0() {
    int aNum = 8;
    func my_func(aNum);
    std::thread my_thread(my_func);
    try
    {
        do_something_in_current_thread(8);
    }
    catch(const int num)
    {
        std::cout << "exception num : " <<num << std::endl;
        throw "An error happened ...";
    }
    catch(const char *error) {
        std::cout << "exception error: " << std::string(error) << std::endl;
        throw "An error happened ...";
    }
    // 如果上文有了throw，这里的代码就不会走了
    std::cout << "my_thread join is called" << std::endl;
    my_thread.join();
}

void do_something_in_current_thread(int num) {
    if (num >10)
    {
        const char *error = "The number you input is too big";
        throw error;
    }
    if (num > 5)
    {
        throw -10;
    }
}

void test_detach() {
    int some_local_state = 100;
    func my_func(some_local_state);
    std::thread my_thread(my_func);
    if (my_thread.joinable())
    {
        my_thread.join();
    }
    
    my_thread.detach();
    // for (size_t i = 0; i < 10; i++)
    // {
    //     std::cout << "主线程在干一些事情" <<std::endl;
    // }
}

void start_thread_with_closure()
{
    std::thread my_thread([]()
                          {
        std::cout << "do some thing in background" << std::endl;
        std::thread::id thread_id = std::this_thread::get_id();
        std::cout << "background thread id: " << thread_id << std::endl; });
    my_thread.join();
}

void start_thread_with_fake_func()
{
    background_task f;
    std::thread my_thread(f);
    if (my_thread.joinable())
    {
        my_thread.join();
    }
    std::cout << "main task thread id: " << std::this_thread::get_id() << std::endl;
    std::cout << "main 中的任务执行完了" << std::endl;
}
